package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.UserLevelListDto;
import com.frejoys.common.dto.common.PageDto;
import com.frejoys.common.enums.EStatus;
import com.frejoys.common.enums.EUserLevelType;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.AppConfigUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.admin.UserLevelAgentVo;
import com.frejoys.common.vo.app.ChildUserCountVo;
import com.frejoys.common.vo.app.RecommendCount;
import com.frejoys.common.vo.app.UserLevelVo;
import com.frejoys.dao.entity.*;
import com.frejoys.dao.mapper.*;
import com.frejoys.service.UserLevelService;
import com.frejoys.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
public class UserLevelServiceImpl extends ServiceImpl<UserLevelMapper, UserLevel> implements UserLevelService {

    private final UserService userService;

    private final UserMapper userMapper;

    private final UserCodeMapper userCodeMapper;

    private final UserLevelMoneyMapper userLevelMoneyMapper;

    private final AgentStoreMapper agentStoreMapper;

    @Override
    public UserLevel getParentInfo(Long childUserId) {
        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserLevel::getChildUserId, childUserId);
        return getOnly(wrapper);
    }

    /**
     *
     * @param id 推荐人id
     * @param userId 被推荐人id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addUserLevel(Long id, Long userId) {
        if (id.equals(userId)){
            throw new GeneralException(HttpStatus.notOwnRelevancyError);
        }
        User user = userService.getInfo(id);
        if (ObjectUtils.isEmpty(user)){
            throw new GeneralException(HttpStatus.extendUserNoExist);
        }

        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserLevel::getId)
                .eq(UserLevel::getChildUserId,userId);
        UserLevel userLevel = getOnly(wrapper);

        if (!ObjectUtils.isEmpty(userLevel)){
            throw new GeneralException(HttpStatus.userLevelError);
        }

        LambdaQueryWrapper<UserLevel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserLevel::getUserId)
                .eq(UserLevel::getChildUserId,id);
        UserLevel userLevels = getOnly(queryWrapper);

        //绑定用户推荐关系
        UserLevel u = new UserLevel();
        u.setChildUserId(userId);
        u.setUserId(id);
        if (userLevels!= null){
            u.setParentUserId(userLevels.getUserId());
        }else {
            u.setParentUserId(0l);
        }
        u.setCreateTime(TimeUtil.unixTime());
        baseMapper.insert(u);

        //查询被推荐人是否推荐人
        LambdaQueryWrapper<UserLevel> userLevelWrapper = new LambdaQueryWrapper<>();
        userLevelWrapper.select(UserLevel::getParentUserId)
                .eq(UserLevel::getUserId,userId);
        UserLevel level = getOnly(userLevelWrapper);

        if (ObjectUtil.isNotEmpty(level) && level.getParentUserId() == 0){
            LambdaUpdateWrapper<UserLevel> upWrapper = new LambdaUpdateWrapper<>();
            upWrapper.eq(UserLevel::getUserId,userId)
                    .set(UserLevel::getParentUserId,id);
            update(upWrapper);
        }

//        //添加代理人邀请码
//        LambdaQueryWrapper<UserCode> userCodeWrapper = new LambdaQueryWrapper<>();
//        userCodeWrapper.select(UserCode::getCode,UserCode::getUserId);
//        List<UserCode> userCodes = userCodeMapper.selectList(userCodeWrapper);
//        List<String> codes = userCodes.stream().map(UserCode::getCode).toList();
//        List<Long> userIds = userCodes.stream().map(UserCode::getUserId).toList();
//
//        if (!userIds.contains(userId)){
//            String code = null;
//            //生成邀请码
//            for (int i = 0;i < 10; i++) {
//                code = null;
//                if (code != null){
//                    break;
//                }
//            }
//            if (code == null){
//                throw new GeneralException(HttpStatus.notCodeError);
//            }
//
//            UserCode userCode = new UserCode();
//            userCode.setCode(code);
//            userCode.setUserId(userId);
//            userCodeMapper.insert(userCode);
//        }

        return true;
    }

    @Override
    public boolean addChildUser(Long userId, Long childUserId) {
        if (userId == null || childUserId == null || userId.equals(childUserId)) {
            return false;
        }

        // 获取被推荐人信息
        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserLevel::getId).eq(UserLevel::getChildUserId,childUserId);
        if (getOnly(wrapper) != null) {
            return false;
        }

        // 获取推荐人信息
        LambdaQueryWrapper<UserLevel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserLevel::getUserId).eq(UserLevel::getChildUserId,userId);
        UserLevel userLevels = getOnly(queryWrapper);


        // 绑定用户推荐关系
        UserLevel u = new UserLevel();
        u.setChildUserId(childUserId);
        u.setUserId(userId);
        if (userLevels!= null){
            u.setParentUserId(userLevels.getUserId());
        }else {
            u.setParentUserId(0l);
        }
        u.setCreateTime(TimeUtil.unixTime());
        baseMapper.insert(u);

        return true;
    }

    @Override
    public IPage<UserLevelAgentVo> userLevelListInfo(UserLevelListDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());

        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper<>();
        if (dto.getUserId() != null){
            if (dto.getType() == EUserLevelType.userLevelTypeUser.getValue()){
                wrapper.eq(UserLevel::getUserId,dto.getUserId());
            }
            if (dto.getType() == EUserLevelType.childUser.getValue()){
                wrapper.eq(UserLevel::getChildUserId,dto.getUserId());
            }
            if (dto.getType() == EUserLevelType.parentUser.getValue()){
                wrapper.eq(UserLevel::getParentUserId,dto.getUserId());
            }
        }
        if (StrUtil.isNotEmpty(dto.getPhone())){

            //根据手机号查询用户id
            Long userId = userMapper.phoneByUserId(dto.getPhone());

            if (dto.getType() == EUserLevelType.userLevelTypeUser.getValue()){
                wrapper.eq(UserLevel::getUserId,userId);
            }
            if (dto.getType() == EUserLevelType.childUser.getValue()){
                wrapper.eq(UserLevel::getChildUserId,userId);
            }
            if (dto.getType() == EUserLevelType.parentUser.getValue()){
                wrapper.eq(UserLevel::getParentUserId,userId);
            }
        }
        if (StrUtil.isNotEmpty(dto.getCode())){

            //根据邀请码查询用户id
            Long userId = userCodeMapper.userIdByCode(dto.getCode());

            if (dto.getType() == EUserLevelType.userLevelTypeUser.getValue()){
                wrapper.eq(UserLevel::getUserId,userId);
            }
            if (dto.getType() == EUserLevelType.childUser.getValue()){
                wrapper.eq(UserLevel::getChildUserId,userId);
            }
            if (dto.getType() == EUserLevelType.parentUser.getValue()){
                wrapper.eq(UserLevel::getParentUserId,userId);
            }
        }
        wrapper.orderByDesc(UserLevel::getCreateTime);
        Page<UserLevel> userLevelAgents = baseMapper.selectPage(page,wrapper);
        IPage<UserLevelAgentVo> userLevelAgentVoIPage = userLevelAgents.convert(userLevel -> BeanUtil.copyProperties(userLevel, UserLevelAgentVo.class));

        List<UserLevelAgentVo> parentList = userLevelAgentVoIPage.getRecords();

        if (!parentList.isEmpty()) {

            List<Long> userIds = parentList.stream().map(UserLevelAgentVo::getUserId).toList();
            List<Long> childUserIds = parentList.stream().map(UserLevelAgentVo::getChildUserId).toList();
            List<Long> parentUserIds = parentList.stream().map(UserLevelAgentVo::getParentUserId).toList();

            //将三组id放到一个list查询用户信息
            List<Long> ids = Stream.of(userIds, childUserIds, parentUserIds).flatMap(List::stream).distinct().collect(Collectors.toList());
            List<User> users = userMapper.getUserByIds(ids);
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, u -> u));

            //查询邀请码
            List<UserCode> userCodes = userCodeMapper.getUserCodeList(ids);
            Map<Long, String> codeMap = userCodes.stream().collect(Collectors.toMap(UserCode::getUserId, UserCode::getCode));
            parentList.forEach(vo ->{
                User user = userMap.get(vo.getUserId());
                if (ObjectUtil.isNotEmpty(user)){
                    vo.setNickname(user.getNickname());
                    vo.setPhone(user.getPhone());
                    vo.setAvatar(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                }
                User childUser = userMap.get(vo.getChildUserId());
                if (ObjectUtil.isNotEmpty(childUser)){
                    vo.setChildNickname(childUser.getNickname());
                    vo.setChildPhone(childUser.getPhone());
                    vo.setChildAvatar(AppConfigUtil.getUrlPrefix(childUser.getAvatar()));
                }
                User parentUser = userMap.get(vo.getParentUserId());
                if (ObjectUtil.isNotEmpty(parentUser)){
                    vo.setParentNickname(parentUser.getNickname());
                    vo.setParentPhone(parentUser.getPhone());
                    vo.setParentAvatar(AppConfigUtil.getUrlPrefix(parentUser.getAvatar()));
                }
                vo.setUserCode(codeMap.get(vo.getUserId()));
                vo.setChildUserCode(codeMap.get(vo.getChildUserId()));
                vo.setParentUserCode(codeMap.get(vo.getParentUserId()));

            });

        }
        return userLevelAgentVoIPage;
    }



    @Override
    public List<UserLevelVo> oneUserLevelInfo(Long userId, PageDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);

        List<UserLevelVo> list = new ArrayList<>();

        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper();
        wrapper.eq(UserLevel::getUserId, userId);

        Page<UserLevel> userLevelPage = baseMapper.selectPage(page, wrapper);
        List<UserLevel> userLevels = userLevelPage.getRecords();

        if (!userLevels.isEmpty()) {
            List<Long> userIds = userLevels.stream().map(UserLevel::getChildUserId).toList();

            //查询用户 头像昵称
            List<User> users = userMapper.getUserList(userIds, EStatus.on.getValue());
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

            //查询每个用户的推广人数
            List<ChildUserCountVo> childUserCountVos = baseMapper.getChildUserCount(userIds);
            Map<Long, Integer> countMap = childUserCountVos.stream().collect(Collectors.toMap(ChildUserCountVo::getUserId, ChildUserCountVo::getChildUserCount));

            //查询推广金额
            List<UserLevelMoney> userLevelMonies = userLevelMoneyMapper.childUserMoneyByUserId(userId);
            Map<Long, BigDecimal> childUserMoneyMap = userLevelMonies.stream().collect(Collectors.toMap(UserLevelMoney::getChildUserId, UserLevelMoney::getMoney));

            if (!userLevels.isEmpty()) {

                userLevels.forEach(userLevel -> {

                    if (userMap.containsKey(userLevel.getChildUserId())){

                        UserLevelVo vo = new UserLevelVo();

                        vo.setId(userLevel.getId());
                        vo.setCreateTime(userLevel.getCreateTime());

                        if (userMap.containsKey(userLevel.getChildUserId())){
                            User user = userMap.get(userLevel.getChildUserId());

                            vo.setUserId(user.getId());
                            vo.setNickname(user.getNickname());
                            vo.setAvatar(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                            vo.setRole(user.getRole());

                            if (countMap.containsKey(user.getId())){
                                vo.setChildUserCount(countMap.get(user.getId()));
                            }
                            if (childUserMoneyMap.containsKey(user.getId())){
                                vo.setChildUserMoney(childUserMoneyMap.get(user.getId()));
                            }
                        }
                        list.add(vo);
                    }
                });
            }
        }
        return list;
    }

    @Override
    public List<UserLevelVo> twoUserLevelInfo(Long userId, PageDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);

        List<UserLevelVo> list = new ArrayList<>();

        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper();
        wrapper.eq(UserLevel::getParentUserId, userId);

        Page<UserLevel> userLevelPage = baseMapper.selectPage(page, wrapper);
        List<UserLevel> userLevels = userLevelPage.getRecords();

        if (!userLevels.isEmpty()) {
            List<Long> userIds = userLevels.stream().map(UserLevel::getChildUserId).toList();

            //查询用户 头像昵称
            List<User> users = userMapper.getUserList(userIds, EStatus.on.getValue());
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

            //查询每个用户的推广人数
            List<ChildUserCountVo> childUserCountVos = baseMapper.getChildUserCount(userIds);
            Map<Long, Integer> countMap = childUserCountVos.stream().collect(Collectors.toMap(ChildUserCountVo::getUserId, ChildUserCountVo::getChildUserCount));

            //查询推广金额
            List<UserLevelMoney> userLevelMonies = userLevelMoneyMapper.childUserMoneyByUserId(userId);
            Map<Long, BigDecimal> childUserMoneyMap = userLevelMonies.stream().collect(Collectors.toMap(UserLevelMoney::getChildUserId, UserLevelMoney::getMoney));

            if (!userLevels.isEmpty()) {

                userLevels.forEach(userLevel -> {

                    if (userMap.containsKey(userLevel.getChildUserId())){

                        UserLevelVo vo = new UserLevelVo();
                        vo.setId(userLevel.getId());
                        vo.setCreateTime(userLevel.getCreateTime());

                        if (userMap.containsKey(userLevel.getChildUserId())){
                            User user = userMap.get(userLevel.getChildUserId());

                            vo.setUserId(user.getId());
                            vo.setNickname(user.getNickname());
                            vo.setAvatar(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                            vo.setRole(user.getRole());

                            if (countMap.containsKey(user.getId())){
                                vo.setChildUserCount(countMap.get(user.getId()));
                            }
                            if (childUserMoneyMap.containsKey(user.getId())){
                                vo.setChildUserMoney(childUserMoneyMap.get(user.getId()));
                            }
                        }

                        list.add(vo);
                    }
                });
            }
        }
        return list;
    }


    @Override
    public UserLevelVo myReference(Long userId) {
        UserLevelVo vo =new UserLevelVo();

        LambdaQueryWrapper<UserLevel> wrapper = new LambdaQueryWrapper();
        wrapper.eq(UserLevel::getChildUserId, userId);

        UserLevel userLevel = getOnly(wrapper);

        if (ObjectUtil.isNotEmpty(userLevel)){

            User user = userService.getInfo(userLevel.getUserId());

            if (ObjectUtil.isNotEmpty(user)){

                vo.setUserId(user.getId());
                vo.setId(userLevel.getId());
                vo.setNickname(user.getNickname());
                vo.setAvatar(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                vo.setRole(user.getRole());
            }
        }

        return vo;
    }


    @Override
    public RecommendCount recommendCount(Long userId) {
        User user = userService.getInfo(userId);

        if (user == null){
            throw new GeneralException(HttpStatus.notUserError);
        }

        Integer userLevelOneCount = baseMapper.userLevelOneCount(userId);
        Integer userLevelTwoCount = baseMapper.userLevelTwoCount(userId);
        Integer storeCount = agentStoreMapper.storeCount(userId);


        RecommendCount r = new RecommendCount();
        r.setNickname(user.getNickname());
        r.setRole(user.getRole());
        r.setUserLevelOneCount(userLevelOneCount);
        r.setUserLevelTwoCount(userLevelTwoCount);
        r.setStoreCount(storeCount);
        return r;
    }
}
